package cn.jinbyte.web.interceptor;

import cn.jinbyte.web.annotation.Idempotent;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 本地缓存幂等性拦截器
 *
 * @author jinty
 */
@Slf4j
public class LocalIdempotentInterceptor extends IdempotentInterceptor {
    private static final ConcurrentHashMap<String, LocalDateTime> idempotencyMap = new ConcurrentHashMap<>();
    private static final long CLEAR_INTERVAL = 300 * 1000; // 5分钟
    private static final Timer timer = new Timer();

    static {
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                clearExpiredKeys();
            }
        }, CLEAR_INTERVAL, CLEAR_INTERVAL);
        log.info("Start ClearExpiredIdempotentKeys TimerTask");
    }

    @Override
    public boolean isIdempotent(HttpServletRequest request, Idempotent idempotent) throws IOException {
        String idempotencyKey = generateIdempotencyKey(request);
        if (!idempotencyMap.containsKey(idempotencyKey)) {
            idempotencyMap.put(idempotencyKey, LocalDateTime.now());
            return false;
        }
        LocalDateTime lastRequestTime = idempotencyMap.get(idempotencyKey);
        long interval = idempotent.interval();
        if (LocalDateTime.now().isAfter(lastRequestTime.plusSeconds(interval))) {
            idempotencyMap.put(idempotencyKey, LocalDateTime.now());
            return false;
        } else {
            return true;
        }
    }

    private static void clearExpiredKeys() {
        LocalDateTime now = LocalDateTime.now();
        idempotencyMap.entrySet().removeIf(entry -> entry.getValue().isBefore(now));
    }
}
